/*
 * @Author: LVGRAPE
 * @LastEditors: LVGRAPE
 */
/**
 **************************************************************************
 * @file     main.c
 * @brief    main program
 **************************************************************************
 *                       Copyright notice & Disclaimer
 *
 * The software Board Support Package (BSP) that is made available to
 * download from Artery official website is the copyrighted work of Artery.
 * Artery authorizes customers to use, copy, and distribute the BSP
 * software and its related documentation for the purpose of design and
 * development in conjunction with Artery microcontrollers. Use of the
 * software is governed by this copyright notice and the following disclaimer.
 *
 * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
 * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
 * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
 * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
 * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
 *
 **************************************************************************
 */
#include "drv_pin.h"
#include "drv_pwm.h"
#include "anoPTv8_report.h"
#include "zino.h"

/** @addtogroup AT32F413_periph_examples
 * @{
 */

/** @addtogroup 413_ADC_tmr_trigger_automatic_preempted ADC_tmr_trigger_automatic_preempted
 * @{
 */
#define DMA_CYCLES 10
#define ADC_CHANNELS 6
#define DMA_BUFFER_SIZE (DMA_CYCLES * ADC_CHANNELS)
#define ADC_CLYCLES ADC_SAMPLETIME_71_5

#define DBG_TAG "adc"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>

__IO uint16_t adc_values[DMA_BUFFER_SIZE] = {0};
__IO uint16_t dma_cnt = 0;
__IO int32_t adc_raw[6] = {0};
float batVol_mv;
float batVol_mv_lpf;
float motorCurrent[4];
float overflowCurrent[4];

static void gpio_config(void);
static void dma_config(void);
static void adc_config(void);

/**
 * @brief  gpio configuration.
 * @param  none
 * @retval none
 */
static void gpio_config(void)
{
    gpio_init_type gpio_initstructure;
    crm_periph_clock_enable(CRM_GPIOC_PERIPH_CLOCK, TRUE);

    gpio_default_para_init(&gpio_initstructure);
    gpio_initstructure.gpio_mode = GPIO_MODE_ANALOG;
    gpio_initstructure.gpio_pins = GPIO_PINS_0 | GPIO_PINS_1 | GPIO_PINS_2 | GPIO_PINS_3 | GPIO_PINS_4 | GPIO_PINS_5;
    gpio_init(GPIOC, &gpio_initstructure);
}

/**
 * @brief  dma configuration.
 * @param  none
 * @retval none
 */
static void dma_config(void)
{
    dma_init_type dma_init_struct;
    crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);
    nvic_irq_enable(DMA1_Channel1_IRQn, 0, 0);
    dma_reset(DMA1_CHANNEL1);
    dma_default_para_init(&dma_init_struct);
    dma_init_struct.buffer_size = DMA_BUFFER_SIZE;
    dma_init_struct.direction = DMA_DIR_PERIPHERAL_TO_MEMORY;
    dma_init_struct.memory_base_addr = (uint32_t)adc_values;
    dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_HALFWORD;
    dma_init_struct.memory_inc_enable = TRUE;
    dma_init_struct.peripheral_base_addr = (uint32_t)&(ADC1->odt);
    dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_HALFWORD;
    dma_init_struct.peripheral_inc_enable = FALSE;
    dma_init_struct.priority = DMA_PRIORITY_HIGH;
    dma_init_struct.loop_mode_enable = TRUE;
    dma_init(DMA1_CHANNEL1, &dma_init_struct);

    dma_interrupt_enable(DMA1_CHANNEL1, DMA_FDT_INT, TRUE);
    dma_channel_enable(DMA1_CHANNEL1, TRUE);
}

/**
 * @brief  adc configuration.
 * @param  none
 * @retval none
 */
static void adc_config(void)
{
    adc_base_config_type adc_base_struct;
    crm_periph_clock_enable(CRM_ADC1_PERIPH_CLOCK, TRUE);
    crm_adc_clock_div_set(CRM_ADC_DIV_6);
    // nvic_irq_enable(ADC1_2_IRQn, 0, 0);

    /* select combine mode */
    adc_combine_mode_select(ADC_INDEPENDENT_MODE);
    adc_base_default_para_init(&adc_base_struct);
    adc_base_struct.sequence_mode = TRUE;
    adc_base_struct.repeat_mode = FALSE;
    adc_base_struct.data_align = ADC_RIGHT_ALIGNMENT;
    adc_base_struct.ordinary_channel_length = 6;
    adc_base_config(ADC1, &adc_base_struct);

    adc_ordinary_channel_set(ADC1, ADC_CHANNEL_10, 1, ADC_CLYCLES);
    adc_ordinary_channel_set(ADC1, ADC_CHANNEL_11, 2, ADC_CLYCLES);
    adc_ordinary_channel_set(ADC1, ADC_CHANNEL_12, 3, ADC_CLYCLES);
    adc_ordinary_channel_set(ADC1, ADC_CHANNEL_13, 4, ADC_CLYCLES);
    adc_ordinary_channel_set(ADC1, ADC_CHANNEL_14, 5, ADC_CLYCLES);
    adc_ordinary_channel_set(ADC1, ADC_CHANNEL_15, 6, ADC_CLYCLES);
    adc_ordinary_conversion_trigger_set(ADC1, ADC12_ORDINARY_TRIG_EXINT11_TMR8TRGOUT, TRUE);
    gpio_pin_remap_config(ADC1_ETO_GMUX, TRUE); // 1：ADC1 普通转换外部触发连接到 TMR8_TRGO
    adc_dma_mode_enable(ADC1, TRUE);

    adc_enable(ADC1, TRUE);
    adc_calibration_init(ADC1);
    while (adc_calibration_init_status_get(ADC1))
        ;
    adc_calibration_start(ADC1);
    while (adc_calibration_status_get(ADC1))
        ;
    // rt_kprintf("adc calibration finish \r\n");
}
/**
 * @brief  this function handles dma1_channel1 handler.
 * @param  none
 * @retval none
 */
void DMA1_Channel1_IRQHandler(void)
{
    rt_enter_critical();
    if (dma_interrupt_flag_get(DMA1_FDT1_FLAG) != RESET)
    {
        dma_cnt++;
        dma_flag_clear(DMA1_FDT1_FLAG);
    }
    rt_exit_critical();
}
/**
 * @brief  main function.
 * @param  none
 * @retval none
 */
int adc_init(void)
{
    gpio_config();
    dma_config();
    adc_config();
    return 0;
}
void adc_calculate(void)
{
    adc_raw[0] = 0;
    adc_raw[1] = 0;
    adc_raw[2] = 0;
    adc_raw[3] = 0;
    adc_raw[4] = 0;
    adc_raw[5] = 0;

    for (int i = 0; i < DMA_BUFFER_SIZE; i += 6)
    {
        adc_raw[0] += adc_values[i + 0];
        adc_raw[1] += adc_values[i + 1];
        adc_raw[2] += adc_values[i + 2];
        adc_raw[3] += adc_values[i + 3];
        adc_raw[4] += adc_values[i + 4];
        adc_raw[5] += adc_values[i + 5];
    }
    adc_raw[0] /= DMA_CYCLES;
    adc_raw[1] /= DMA_CYCLES;
    adc_raw[2] /= DMA_CYCLES;
    adc_raw[3] /= DMA_CYCLES;
    adc_raw[4] /= DMA_CYCLES;
    adc_raw[5] /= DMA_CYCLES;

    batVol_mv = (float)adc_raw[4] * 1.0498046875f; //* 3.3 * 1000 / 4096 / (33 / (33 + 10))

    if (millis() < 1000)
    {
        batVol_mv_lpf = batVol_mv;
    }
    else
    {
        batVol_mv_lpf += (batVol_mv - batVol_mv_lpf) * 0.01f;
    }

// motorCurrent[0] = adc_raw[0] * 34.9934895833333f; //* 3.3 * 1000 / 4096 / (33 / (33 + 10)) /0.03
// motorCurrent[1] = adc_raw[1] * 34.9934895833333f;
// motorCurrent[2] = adc_raw[2] * 34.9934895833333f;
// motorCurrent[3] = adc_raw[3] * 34.9934895833333f;

/**
 * @brief
 *  4.0V 20% ~ 90%
 *      1700~1300
 *  3.0V 20% ~ 90%
 *      1400~1000
 */
#define BASE_CUR 1000
    for (uint8_t i = 0; i < 4; i++)
    {
        // float vbatFix = (batVol_mv_lpf - 3000) / 333.3f;

        float cur = adc_raw[i] * 1.0498046875f; // 实际测到电压
        motorCurrent[i] += (cur - motorCurrent[i]) * 0.1f;

        // overflowCurrent[i] = motorCurrent[i] - (motor_values[i] * 0.01f) + (batVol_mv_lpf - 3000) * 0.05f;
        // if (motor_values[i] > 200)
        // {
        // }
        // else
        // {
        //     overflowCurrent[i] = 0;
        // }
    }

    // F2_wave[2] = motorCurrent[0];
    // F2_wave[3] = motorCurrent[1];
    // F2_wave[4] = motorCurrent[2];
    // F2_wave[5] = motorCurrent[3];
    // F2_wave[6] = overflowCurrent[0];
    // F2_wave[7] = overflowCurrent[1];
    // F2_wave[8] = overflowCurrent[2];
    // F2_wave[9] = overflowCurrent[3];

    // LOG_D("ADC:%d vbat:%d \n", adc_raw[4], batVol_mv);
    // rt_kprintf("adc value: %d, %d, %d, %d, %d, %d, %d\r\n", adc_raw[0], adc_raw[1], adc_raw[2], adc_raw[3], adc_raw[4], adc_raw[5], dma_cnt);
    // rt_kprintf("adc value: %d, %d, %d, %d, %d, %d, %d\r\n", adc_values[6], adc_values[7], adc_values[8], adc_values[9], adc_values[10], adc_values[11], dma_cnt);
    // rt_kprintf("adc value: %d, %d, %d, %d, %d, %d [%d]\r\n", adc1_preempt_valuetab[0], adc1_preempt_valuetab[1], adc1_preempt_valuetab[2], adc1_preempt_valuetab[3], adc1_preempt_valuetab[4], adc1_preempt_valuetab[5],dma_cnt);
    dma_cnt = 0;
}

int16_t get_vbat_voltage_mv(void)
{
    return batVol_mv_lpf;
}

uint16_t get_m1_current_ma()
{
    return motorCurrent[0];
}
uint16_t get_m2_current_ma()
{
    return motorCurrent[1];
}
uint16_t get_m3_current_ma()
{
    return motorCurrent[2];
}
uint16_t get_m4_current_ma()
{
    return motorCurrent[3];
}
/**
 * @}
 */

/**
 * @}
 */
